{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e0785c9a-7bee-4bd3-9173-c93fb70c8e03",
   "metadata": {},
   "source": [
    "# QSVT\n",
    "\n",
    "The Quantum Singlar Value Transformation (QSVT) [[1]](#QSVT) is an algorithmic framework, used to apply polynomial transformation on the singular values of a block encoded matrix. It has wide range of applications such as matrix inversion, amplitude amplification and hamiltonian simulation.\n",
    "\n",
    "Given a unitary $U$, a list of phase angles  $\\phi_1, \\phi_2, ..., \\phi_{d+1}$ and 2 projector-controlled-not operands $C_{\\Pi}NOT,C_{\\tilde{\\Pi}}NOT$ , the QSVT sequence is as follows:\n",
    "\n",
    "$$ \\tilde{\\Pi}_{\\phi_{d+1}} \\prod_{k=1}^{(d-1)/2} (\\Pi_{\\phi_{d-2k}} U^{\\dagger}\\tilde{\\Pi}_{\\phi_{d - (2k+1)}}U)\\Pi_{\\phi_{1}} $$\n",
    "for odd $d$, and:\n",
    "$$ \\prod_{k=1}^{d/2} (\\Pi_{\\phi_{d-(2k-1)}} U^{\\dagger}\\tilde{\\Pi}_{\\phi_{d-2k}}U)\\Pi_{\\phi_{1}}$$\n",
    "for even $d$.\n",
    "\n",
    "Each of the projector-controlled-phase unitaries $\\Pi$ consists of a $Z$ rotation of an auxilliary qubit wrapped by the $C_{\\Pi}NOT$s, NOTing the auxilliary qubit:\n",
    "$$\\Pi_{\\phi} = (C_{\\Pi}NOT) e^{-i\\frac{\\phi}{2}Z}(C_{\\Pi}NOT)$$\n",
    "The transformation will result with a polynomial of order $d$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f8b8021-5b76-4ad6-ae3e-469434cf316f",
   "metadata": {},
   "source": [
    "Function: `qsvt`\n",
    "\n",
    "Arguments:\n",
    "\n",
    "- `phase_seq: CArray[CReal]` - a $d+1$ sized sequence of phase angles.\n",
    "- `proj_cnot_1: QCallable[QArray[QBit], QBit]` - projector-controlled-not unitary that locates the encoded matrix columns within $U$. Accepts quantum variable of the size of `qvar`, and a qubit that is set to $|1\\rangle$ when the state is in the block.\n",
    "- `proj_cnot_2: QCallable[QArray[QBit], QBit]` - projector-controlled-not unitary that locates the encoded matrix rows within $U$. Accepts quantum variable of the size of `qvar`, and a qubit that is set to $|1\\rangle$ when the state is in the block.\n",
    "- `u: QCallable[QArray[QBit]]` - $U$ a block encoding unitary of a matrix $A$, such that $A = \\tilde{\\Pi}U\\Pi$.\n",
    "- `qvar: QArray[QBit]` - the quantum variable on which $U$ applies, which resides in the entire block encoding space.\n",
    "- `aux: QBit` - a zero auxilliary qubit, used for the projector-controlled-phase rotations. Given as an input so that qsvt can be used as a building-block in a larger algorithm."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c0e5a6f-c671-4126-a359-a0c797f5a778",
   "metadata": {},
   "source": [
    "### Example: polynomial transformation on a $\\sqrt(x)$ block encoding\n",
    "\n",
    "The following example implements a random polynomial transformation on a given block, based on [[2]](#QSVT_derivative).\n",
    "The unitary $U$ here is a square-root transformation: $U|x\\rangle_n|0\\rangle_{n+1} = |x\\rangle_n(\\sqrt{x}|\\psi_0\\rangle_{n}|0\\rangle + \\sqrt{1-x}|\\psi_1\\rangle_{n}|1\\rangle)$ where $x$ is a fixed-point variable in the range $[0, 1)$.\n",
    "\n",
    "The example samples a random odd-polynomial, calculates the necessary phase sequence using the package `pyqsp`, then applies the qsvt and verifies the results.\n",
    "\n",
    "There are 2 distinct projector-controlled-not unitaries - one is applying on the entire $(n+1)$ variable, and the second is on the 1-qubits auxilliary in the image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "05e442a6-6045-4afc-98d9-bb4c566e69c2",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:19.263341Z",
     "iopub.status.busy": "2024-05-07T13:25:19.262732Z",
     "iopub.status.idle": "2024-05-07T13:25:22.027083Z",
     "shell.execute_reply": "2024-05-07T13:25:22.026278Z"
    }
   },
   "outputs": [],
   "source": [
    "from typing import Dict, Tuple\n",
    "\n",
    "import numpy as np\n",
    "from numpy.polynomial import Polynomial\n",
    "from pyqsp.angle_sequence import QuantumSignalProcessingPhases\n",
    "\n",
    "from classiq import (\n",
    "    Constraints,\n",
    "    execute,\n",
    "    set_execution_preferences,\n",
    "    synthesize,\n",
    "    write_qmod,\n",
    ")\n",
    "from classiq.execution import ClassiqBackendPreferences, ExecutionPreferences\n",
    "from classiq.qmod import (\n",
    "    CArray,\n",
    "    CReal,\n",
    "    Output,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    QNum,\n",
    "    X,\n",
    "    allocate,\n",
    "    bind,\n",
    "    control,\n",
    "    create_model,\n",
    "    hadamard_transform,\n",
    "    qfunc,\n",
    "    qsvt,\n",
    ")\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def projector_cnot(reg: QNum, aux: QBit) -> None:\n",
    "    control(reg == 0, lambda: X(aux))\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def u_sqrt(a: QNum, ref: QNum, res: QBit) -> None:\n",
    "    hadamard_transform(ref)\n",
    "    res ^= a <= ref\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def qsvt_sqrt_polynomial(\n",
    "    qsvt_phases: CArray[CReal], state: QNum, ref: QNum, ind: QBit, qsvt_aux: QBit\n",
    ") -> None:\n",
    "    full_reg = QArray[QBit](\"full_reg\")\n",
    "    bind([ind, ref, state], full_reg)\n",
    "\n",
    "    qsvt(\n",
    "        qsvt_phases,\n",
    "        lambda reg_, aux_: projector_cnot(reg_[0 : NUM_QUBITS + 1], aux_),  # ind+ref\n",
    "        lambda reg_, aux_: projector_cnot(reg_[0], aux_),  # ind\n",
    "        lambda reg_: u_sqrt(\n",
    "            reg_[1 + NUM_QUBITS : reg_.len], reg_[1 : 1 + NUM_QUBITS], reg_[0]\n",
    "        ),\n",
    "        full_reg,\n",
    "        qsvt_aux,\n",
    "    )\n",
    "    bind(full_reg, [ind, ref, state])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9d9b57a7-dcd7-4cae-ac42-99bea06f1c11",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:22.032660Z",
     "iopub.status.busy": "2024-05-07T13:25:22.031168Z",
     "iopub.status.idle": "2024-05-07T13:25:22.046033Z",
     "shell.execute_reply": "2024-05-07T13:25:22.045340Z"
    }
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def sample_random_polynomial(degree):\n",
    "    # Generate random coefficients\n",
    "    coefficients = np.random.uniform(-1, 1, degree + 1)\n",
    "    # take care for parity\n",
    "    coefficients[int(degree + 1) % 2 :: 2] = 0\n",
    "\n",
    "    # Create the polynomial\n",
    "    p = Polynomial(coefficients)\n",
    "    # Evaluate the polynomial over the interval [-1, 1]\n",
    "    x = np.linspace(-1, 1, 500)\n",
    "    y = p(x)\n",
    "\n",
    "    # Normalize the polynomial\n",
    "    poly = p / np.max(np.abs(y))\n",
    "    print(poly)\n",
    "    return poly\n",
    "\n",
    "\n",
    "def adjust_qsvt_convetions(phases: np.ndarray) -> np.ndarray:\n",
    "    phases = np.array(phases)\n",
    "    # change the R(x) to W(x), as the phases are in the W(x) conventions\n",
    "    phases = phases - np.pi / 2\n",
    "    phases[0] = phases[0] + np.pi / 4\n",
    "    phases[-1] = phases[-1] + np.pi / 2 + (2 * DEGREE - 1) * np.pi / 4\n",
    "\n",
    "    # verify conventions. minus is due to exp(-i*phi*z) in qsvt in comparison to qsp\n",
    "    return -2 * phases\n",
    "\n",
    "\n",
    "def compute_qsvt_phases(poly):\n",
    "    phases = QuantumSignalProcessingPhases(\n",
    "        poly, signal_operator=\"Wx\", method=\"laurent\", measurement=\"x\"\n",
    "    )\n",
    "    return adjust_qsvt_convetions(phases).tolist()\n",
    "\n",
    "\n",
    "def parse_qsvt_results(res) -> Tuple[np.ndarray, np.ndarray]:\n",
    "    parsed_state_vector = res[0].value.parsed_state_vector\n",
    "\n",
    "    d: Dict = {x: [] for x in range(2**NUM_QUBITS)}\n",
    "    for parsed_state in parsed_state_vector:\n",
    "        if (\n",
    "            parsed_state[\"qsvt_aux\"] == 0\n",
    "            and parsed_state[\"ind\"] == 0\n",
    "            and np.linalg.norm(parsed_state.amplitude) > 1e-15\n",
    "            and (DEGREE % 2 == 1 or parsed_state[\"ref\"] == 0)\n",
    "        ):\n",
    "            d[parsed_state[\"state\"]].append(parsed_state.amplitude)\n",
    "    d = {k: np.linalg.norm(v) for k, v in d.items()}\n",
    "    values = [d[i] for i in range(len(d))]\n",
    "\n",
    "    x = np.sqrt(np.linspace(0, 1 - 1 / (2**NUM_QUBITS), 2**NUM_QUBITS))\n",
    "\n",
    "    measured_poly_values = np.sqrt(2**NUM_QUBITS) * np.array(values)\n",
    "    target_poly_values = np.abs(POLY(x))\n",
    "\n",
    "    plt.scatter(x, measured_poly_values, label=\"measured\", c=\"g\")\n",
    "    plt.plot(x, target_poly_values, label=\"target\")\n",
    "    plt.xlabel(r\"$\\sqrt{x}$\")\n",
    "    plt.ylabel(r\"$P(\\sqrt{x})$\")\n",
    "    plt.legend()\n",
    "\n",
    "    return measured_poly_values, target_poly_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "736314d2-bcc9-4f08-a7c8-93fe6a788a74",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:22.050620Z",
     "iopub.status.busy": "2024-05-07T13:25:22.049464Z",
     "iopub.status.idle": "2024-05-07T13:25:22.074785Z",
     "shell.execute_reply": "2024-05-07T13:25:22.074029Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.0 + 0.57226496\u00b7x + 0.0\u00b7x\u00b2 - 0.5134161\u00b7x\u00b3 + 0.0\u00b7x\u2074 - 1.05884886\u00b7x\u2075\n"
     ]
    }
   ],
   "source": [
    "NUM_QUBITS = 4\n",
    "DEGREE = 5\n",
    "\n",
    "np.random.seed(1)\n",
    "\n",
    "# choosing in purpose odd polynomial\n",
    "POLY = sample_random_polynomial(DEGREE)\n",
    "QSVT_PHASES = compute_qsvt_phases(POLY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "f6eb063c-f003-4ae2-8a75-acd477260f82",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:22.079812Z",
     "iopub.status.busy": "2024-05-07T13:25:22.078723Z",
     "iopub.status.idle": "2024-05-07T13:25:30.862505Z",
     "shell.execute_reply": "2024-05-07T13:25:30.861874Z"
    }
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def main(\n",
    "    state: Output[QNum],\n",
    "    ref: Output[QNum],\n",
    "    ind: Output[QBit],\n",
    "    qsvt_aux: Output[QBit],\n",
    ") -> None:\n",
    "    allocate(NUM_QUBITS, state)\n",
    "    allocate(NUM_QUBITS, ref)\n",
    "    allocate(1, ind)\n",
    "    allocate(1, qsvt_aux)\n",
    "\n",
    "    hadamard_transform(state)\n",
    "    qsvt_sqrt_polynomial(QSVT_PHASES, state, ref, ind, qsvt_aux)\n",
    "\n",
    "\n",
    "execution_preferences = ExecutionPreferences(\n",
    "    num_shots=1,\n",
    "    backend_preferences=ClassiqBackendPreferences(\n",
    "        backend_name=\"aer_simulator_statevector\"\n",
    "    ),\n",
    ")\n",
    "\n",
    "constraints = Constraints(max_width=13)\n",
    "qmod = create_model(main, constraints=constraints)\n",
    "qmod = set_execution_preferences(qmod, execution_preferences)\n",
    "\n",
    "write_qmod(qmod, \"qsvt\")\n",
    "qprog = synthesize(qmod)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "fe3b426b-cd7b-4568-9e85-8565dd03295e",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T13:25:30.865336Z",
     "iopub.status.busy": "2024-05-07T13:25:30.864844Z",
     "iopub.status.idle": "2024-05-07T13:25:34.873974Z",
     "shell.execute_reply": "2024-05-07T13:25:34.873212Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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7t2bsrIyAAYMGMDevXv5+OOP+fzzz5kwYQKJiYksW7bMuRO6YfzS+1XbbvetWrVyfn3y5EkAVqxYQURERLV2Npvtwi6EiIg0GYvZwvxR8/ntW49gwkyFKQeH6QRQGXoAUkaluGw9H7cKPvPmzWP69OlMmzYNgIULF7JixQoWL15c45iNtWvXcvnll3PzzTcDEBMTw6RJk/j2229rfY3S0lJKS0ud3xcUFDTwu/jFhXbjuaq770wDBgzg3XffJSYmBi+vs/9aHD16lB07drBo0SISEipT+po1a85qFxAQwMSJE5k4cSLjx49n1KhRHDt2jPbt2wOQnZ1N//79AaoNdK5Nr169sNlsZGZmMmzYsBrb9OzZkw8++KDasW+++ea8zy0iIo1jXM9x3HKJhY83Ve/tiQyIJGVUitbxgcoZQRs2bCAxMdF5zGw2k5iYyLp162o8Z+jQoWzYsMF5O2zPnj2sXLmS6667rtbXSU5OJjAw0PmIiopq2DdyhqruvqqE+99c3d13phkzZnDs2DEmTZrEd999x+7du/nkk0+YNm0adrudNm3a0K5dO/7xj3+wa9cuvvjiC5KSkqo9x7x583jrrbfYvn07O3fu5J133iE0NJSgoCB8fX257LLLnIOWv/zyS+f4o3Px9/fn3nvv5Z577uG1115j9+7dbNy4keeee47XXnsNgD/+8Y/8/PPP/O///i87duzgzTff5NVXX22MyyQiIheovCQcgOnx1/DmuDdZNXUVe2fudWnoATcKPnl5edjtdue4kyohISHk5OTUeM7NN9/MI488whVXXIG3tzedO3dm+PDh/OUvf6n1dWbPnk1+fr7zkZWV1aDv40xV3X3AWeHHHbr7zhQeHs7XX3+N3W7n2muvpU+fPsyaNYugoCDMZjNms5klS5awYcMGevfuzT333MPTTz9d7Tn8/f156qmnGDRoEJdeein79u1j5cqVzttcixcvpqKigoEDBzJr1iweffTRC6rtb3/7Gw899BDJycn07NmTUaNGsWLFCmJjYwGIjo7m3Xff5f3336dfv34sXLiw2iBtERFpWoZhsCnzBADj4wYxqc8khscMd4vPO5Nx5qALFzp06BARERGsXbu22sDU++67jy+//LLG21fp6encdNNNPProo8THx7Nr1y5mzpzJ9OnTeeihhy7odQsKCggMDCQ/P5+AgIBqPyspKWHv3r3Exsbi4+NT7/dW07LdUQFRLu/u82QN9WcrIiJnyzxazJVPr8JqMfPDw9di82r4wHOuz+9zcZsxPsHBwVgsFnJzc6sdz83NJTQ0tMZzHnroISZPnsxtt90GQJ8+fSgqKuL222/ngQcecPY0uNq4nuMY232s223UJiIi0hg2ZR0HoFd4QKOEnovhHskAsFqtDBw4kLS0NOcxh8NBWlparVOTi4uLzwo3FkvlBXaTjiwni9nC8JjhbtXdJyIi0hiqbnP1jw5yaR01cZseH4CkpCSmTp3KoEGDGDx4MCkpKc4tFgCmTJlCRESEcxuEMWPGMG/ePPr37++81fXQQw8xZswYZwASERGRprUp6wQAcVFBLq2jJm4VfCZOnMiRI0eYM2cOOTk5xMXFkZqa6hzwnJmZWa2H58EHH8RkMvHggw9y8OBB2rdvz5gxY3jsscdc9RZEREQ8Wkm5nW2H8gEYEN3GxdWczW0GN7tKUwxuFvejP1sRkcaxYf9xfvPiWoJbW/nugUTnYrkNrb6Dm91mjI+IiIg0f5syKwc2x0W1abTQczEUfERERKTBbD49vscdBzaDgo+IiIg0IOeMLjcc2AwKPiIiItJADheUcPDEKUwm6KvgIyIiIi1Z1TT27iH+tLa51cRxJwWfFmr48OHMmjXL1WU4uVs9IiLS8Nx54cIqCj5Sq7KyMleXICIizcjm01tV9I9yv/V7qij4tEC33HILX375JfPnz8dkMmEymdi9eze33norsbGx+Pr60r17d+bPn3/WeTfccAOPPfYY4eHhdO/eHYC1a9cSFxeHj48PgwYN4v3338dkMrF582bnuT/++CO/+tWvaN26NSEhIUyePJm8vLxa69m3b19TXQ4REWkCFXYHWw9ULlwY58Y9Pu55A86NGYbBqXJ7k7+ur7flgtdDmD9/Pjt37qR379488sgjALRp04bIyEjeeecd2rVrx9q1a7n99tsJCwtjwoQJznPT0tIICAjgs88+AyoXiBozZgzXXXcdb775Jvv37z/rltWJEye46qqruO222/i///s/Tp06xZ///GcmTJjAF198UWM97du3b4CrIiIi7mJn7kmKy+z427zo0r61q8uplYJPHZ0qt9NrzidN/rrbHhmJn/XC/rgCAwOxWq34+flV29n+4Ycfdn4dGxvLunXrWLp0abXg06pVK/75z39itVoBWLhwISaTiUWLFuHj40OvXr04ePAg06dPd57z/PPP079/fx5//HHnscWLFxMVFcXOnTvp1q1bjfWIiEjLUbUje7+oIMxm91u4sIqCjwdZsGABixcvJjMzk1OnTlFWVkZcXFy1Nn369HGGHoAdO3bQt2/fats6DB48uNo5W7ZsYdWqVbRufXbC3717N926dWvYNyIiIm6nOQxsBgWfOvP1trDtkZEued2LsWTJEu69916effZZhgwZgr+/P08//TTffvtttXatWrWq83OfPHmSMWPG8OSTT571s7CwsHrXLCIizcdmN96R/UwKPnVkMpku+JaTK1mtVuz2X8Yiff311wwdOpQ777zTeWz37t3nfZ7u3bvz+uuvU1pais1mA+C7776r1mbAgAG8++67xMTE4OVV87X573pERKTlyD9Vzq7DJwH3Dz6a1dVCxcTE8O2337Jv3z7y8vLo2rUr33//PZ988gk7d+7koYceOivA1OTmm2/G4XBw++23k5GRwSeffMIzzzwD4BxsPWPGDI4dO8akSZP47rvv2L17N5988gnTpk1zhp3/rsfhcDTemxcRkSa15XRvT8d2frRrbXNtMeeh4NNC3XvvvVgsFnr16kX79u0ZOXIk48aNY+LEicTHx3P06NFqvT+1CQgI4MMPP2Tz5s3ExcXxwAMPMGfOHADnuJ/w8HC+/vpr7HY71157LX369GHWrFkEBQVhNptrrCczM7Px3ryIiDQpd9+f60wmwzAMVxfhSgUFBQQGBpKfn09AQEC1n5WUlLB3715iY2OrDe71dG+88QbTpk0jPz8fX19fV5dTL/qzFRFpONNeWc+qHUd4+NeXMHVoTJO85rk+v8/F/QeriMv961//olOnTkRERLBlyxbnGj3NNfSIiEjDMQzDuUeXu4/vAQUfuQA5OTnMmTOHnJwcwsLCuPHGG3nsscdcXZaIiLiBfUeLOVFcjtXLTM+wC+95cRUFHzmv++67j/vuu8/VZYiIiBvalFm5cGGfiECsXu4/dNj9KxQRERG31ZwGNoOCzwXx8PHfLZL+TEVEGkbVwoX9o913R/YzKficg7e3NwDFxcUurkQaWllZGQAWy8WtiC0i4slOldnJyC4A3HtH9jNpjM85WCwWgoKCOHz4MAB+fn4XvEO6uC+Hw8GRI0fw8/OrdaVpERE5vx8P5VPhMOjg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389vtxnjIyIiIg1jXM9xLJuwDH8uA+CUpXIdn8iAyBYRei6GW93qEhERkYbRv/1ITPZ0LGZ4/oa7iG37GAnRCR45hf1MCj4iIiIt0Krtlftcxse2Y9qA0S6uxn3oVpeIiEgLtGpHZfAZ0b2DiytxLwo+IiIiLUxRaQXf7jkGwIgeCj5nUvARERFpYb7elUeZ3UF0Wz86t2/l6nLcioKPiIhIC1N1m+uqHh0wmUwursa9KPiIiIi0IIZhsGr7EQCGd2/v4mrcj4KPiIhIC5KRXUhOQQm+3hYu69TO1eW4HQUfERGRFqTqNtflXdrh4+3Za/bURMFHRESkBfni9Po9wzWNvUYKPiIiIi3E8aIyNmUeBzSNvTYKPiIiIi3EVz8fwWFAj1B/IoJ8XV2OW7roLSvKy8vJycmhuLiY9u3b07Zt24aoS0REROqo6jaXentqV68en8LCQl588UWGDRtGQEAAMTEx9OzZk/bt29OxY0emT5/Od99919C1ioiISC3sDoMvd1ZOY9c2FbWrc/CZN28eMTExvPLKKyQmJvL++++zefNmdu7cybp165g7dy4VFRVce+21jBo1ip9//rkx6hYREZEzbM46zonicgJ9vRkQHeTqctxWnW51WSwWJk6cyFdffcUll1xSY5vBgwfz+9//noULF/LKK6+wevVqunbt2iDFioiISM2qbnNd2a09XhYN4a1NnYKPYRi8+eabF9TWZrPxxz/+sV5FiYiISN18sb3qNpdWaz6XOkVC7fchIiLifnLyS8jILsBkgmHdFHzO5aL6wgoLCxuqDhEREamnqtWa46KCaNfa5uJq3NtFBZ+EhARycnIaqhYRERGpB+c0ds3mOq+LCj79+/cnPj6e7du3Vzu+efNmrrvuuosqTERERM6vtMLO17vyALhK6/ec10UFn1deeYVbbrmFK664gjVr1rBz504mTJjAwIEDsVi0MZqIiEhjW7/3GMVldjr427gkPMDV5bi9i165+eGHH8Zms3HNNddgt9u5+uqrWbduHYMHD26I+kREROQczrzNpUlI53dRPT65ubnMnDmTRx99lF69euHt7c0tt9yi0CMiItJEVjm3qdBsrgtxUcEnNjaWr776infeeYcNGzbw7rvvcvvtt/P00083VH0iIiJSi715Rew7Woy3xcQVXRV8LsRF3epavHgxN910k/P7UaNG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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "res = execute(qprog).result()\n",
    "\n",
    "measured, target = parse_qsvt_results(res)\n",
    "assert np.allclose(measured, target, atol=0.02)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1b17715-4b7d-4717-a24d-ac8279df32ca",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "<a id='QSVT'>[1]</a>: Andr\u00e1s Gily\u00e9n, Yuan Su, Guang Hao Low, and Nathan Wiebe. 2019. Quantum singular value transformation and beyond: exponential improvements for quantum matrix arithmetics. In Proceedings of the 51st Annual ACM SIGACT Symposium on Theory of Computing (STOC 2019). Association for Computing Machinery, New York, NY, USA, 193\u2013204 https://doi.org/10.1145/3313276.3316366.\n",
    "\n",
    "<a id='QSVT_derivative'>[2]</a>: Stamatopoulos, Nikitas, and William J. Zeng. \"Derivative pricing using quantum signal processing.\" arXiv preprint arXiv:2307.14310 (2023).\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
